/* eslint-disable */
import { fetch } from 'dva';
import { notification, message, Modal } from 'antd';
import router from 'umi/router';
import hash from 'hash.js';
import { stringify } from 'qs';

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '发出的请求针对的是不存在的记录，服务器没有进行操作。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
};

const checkStatus = response => {
  if (response.status >= 200 && response.status < 400) {
    return response;
  }
  const errortext = codeMessage[response.status] || response.statusText;
  notification.error({
    message: `请求错误 ${response.status}: ${response.url}`,
    description: errortext,
  });
  // if (status === 401) {
  //   // @HACK
  //   /* eslint-disable no-underscore-dangle */
  //   window.g_app._store.dispatch({
  //     type: 'login/logout',
  //   });
  // }
  // // environment should not be used
  // if (status === 403) {
  //   router.push('/exception/403');
  // }
  // if (status <= 504 && status >= 500) {
  //   router.push('/exception/500');
  // }
  // if (status >= 404 && status < 422) {
  //   router.push('/exception/404');
  // }
  const error = new Error(errortext);
  error.name = response.status;
  error.response = response;
};

const cachedSave = (response, hashcode) => {
  /**
   * Clone a response data and store it in sessionStorage
   * Does not support data other than json, Cache only json
   */
  const contentType = response.headers.get('Content-Type');
  if (contentType && contentType.match(/application\/json/i)) {
    // All data is saved as text
    response
      .clone()
      .text()
      .then(content => {
        sessionStorage.setItem(hashcode, content);
        sessionStorage.setItem(`${hashcode}:timestamp`, Date.now());
      });
  }
  return response;
};

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [option] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
function request(url, option) {
  const options = {
    ...option,
  };
  /**
   * Produce fingerprints based on url and parameters
   * Maybe url has the same parameters
   */
  const fingerprint = url + (options.body ? JSON.stringify(options.body) : '');
  const hashcode = hash
    .sha256()
    .update(fingerprint)
    .digest('hex');

  const defaultOptions = {
    // credentials: 'include',
  };
  const newOptions = { ...defaultOptions, ...options };
  if (
    newOptions.method === 'POST' ||
    newOptions.method === 'PUT' ||
    newOptions.method === 'GET' ||
    newOptions.method === 'DELETE'
  ) {
    if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        ...newOptions.headers,
      };
      newOptions.mode = 'cors';
      newOptions.body = JSON.stringify(newOptions.body);
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        Accept: 'application/json',
        ...newOptions.headers,
      };
    }
  }

  const expirys = options.expirys && 60;
  // options.expirys !== false, return the cache,
  if (options.expirys !== false) {
    const cached = sessionStorage.getItem(hashcode);
    const whenCached = sessionStorage.getItem(`${hashcode}:timestamp`);
    if (cached !== null && whenCached !== null) {
      const age = (Date.now() - whenCached) / 1000;
      if (age < expirys) {
        const response = new Response(new Blob([cached]));
        return response.json();
      }
      sessionStorage.removeItem(hashcode);
      sessionStorage.removeItem(`${hashcode}:timestamp`);
    }
  }
  let baseApi = window.localStorage.getItem('VISUAL_API');
  return fetch(baseApi + url, newOptions)
    .then(checkStatus)
    .then(response => cachedSave(response, hashcode))
    .then(response => {
      //先将json返回，由下面的then接收
      // DELETE and 204 do not return data by default
      // using .json will report an error.
      if (newOptions.method === 'DELETE' || response.status === 204) {
        return response.text();
      }
      return response.json();
    })
    .then(response => {
      //对返回数据里面的状态码进行处理，200返回response内的data数据，其他状态部分统一处理，并抛出错误
      if (response.code >= 0) {
        return response;
      }
      let code = response.code;
      if (code === -11) {
        // @HACK
        /* eslint-disable no-underscore-dangle */
        router.push({
          pathname: `/user/login/`,
        });

        // window.g_app._store.dispatch({
        //   type: 'user/login',
        // });
        return;
      }
      message.error(response.msg);
      throw response;
    });
}

function zbkOptions(option) {
  // console.log('AUTH: ', window.sessionStorage.getItem('auth'))

  const headers = {
    Auth: window.sessionStorage.getItem('auth'),
    Appid: '1',
  };
  return {
    headers,
    mode: 'cors',
    ...option,
  };
}

export async function zbkExport(api, option) {
  let baseApi = window.localStorage.getItem('VISUAL_API');
  if (!baseApi) {
    baseApi = await getBaseApi();
    if (!baseApi) {
      return;
    }
  }
  let url = `${baseApi}${api}`;
  let options = zbkOptions(option);
  return fetch(url, options);
}

export function zbkDownload(api, option) {
  zbkExport(api, {})
    .then(res => {
      if (res.status === 200) {
        let filename = res.headers.get('Content-Disposition');
        if (!filename) {
          return res.json();
        }
        res.blob().then(blob => {
          const a = document.createElement('a');
          const url = window.URL.createObjectURL(blob);
          filename = filename.split('filename=')[1];
          filename = filename.replace('"', '').replace('"', '')
          a.href = url;
          a.download = filename;
          a.click();
          window.URL.revokeObjectURL(url);
        });
        return true;
      } else {
        return false;
      }
    }).then(ret => {
      if (ret === true) {
        message.success('下载成功')
      } else if (ret === false) {
        message.error('下载失败')
      } else {
        message.error(ret.msg);
      }
    });
}

export async function zbkRequest(api, option) {

  let baseApi = window.localStorage.getItem('VISUAL_API');
  let kd3000_url = window.localStorage.getItem('KD3000_URL');

  if (!baseApi || !kd3000_url) {
    baseApi = await getBaseApi();
    if (!baseApi) {
      return;
    }
  }
  let url = `${baseApi}${api}`;
  let options = zbkOptions(option);
  return fetch(url, options)
    .then(checkStatus)
    .then(response => response.json())
    .then(response => {
      //对返回数据里面的状态码进行处理，200返回response内的data数据，其他状态部分统一处理，并抛出错误
      if (response.code >= 0) {
        return response;
      }
      if (response.code === -11) {
        const { data: { msg } } = response;
        if (msg) {
          message.warn(msg);
        } else {
          window.sessionStorage.auth && message.warn("登录信息已过期");
        }
        window.sessionStorage.removeItem('auth');
        router.push("/login");

        // if (kd3000_url) {
        //   window.location.href = kd3000_url
        // }
      } else {
        if (response.msg) {
          message.error(response.msg);
        }
      }        
      throw response;
    });
}

export function zbkGet(api, params) {
  if (!params) {
    return zbkRequest(api);
  }
  let queryParams = stringify(params);
  let uri = queryParams ? `${api}?${queryParams}` : api;
  return zbkRequest(uri);
}

export function zbkPost(api, params) {
  let body = null;
  if (params instanceof FormData) {
    body = params;
  } else if (params instanceof Object) {
    body = new FormData();
    Object.keys(params).forEach(key => {
      if (params[key] instanceof Array) {
        for (let v of params[key]) {
          body.append(key, v);
        }
      } else {
        body.append(key, params[key] !== undefined ? params[key] : '');
      }
    });
  } else {
    body = null;
  }
  let option = {
    method: 'POST',
    body,
  };
  return zbkRequest(api, option);
}


export function getBaseApi() {
  const { host, port } = window.location;
  if (port == 8001) {
    let baseApi = VISUAL_API;
    if (!baseApi) {
      let baseApi = `http://${host}:81`;
    }
    window.localStorage.setItem('VISUAL_API', baseApi);
    window.localStorage.setItem('KD3000_URL', KD3000_URL);
    window.localStorage.setItem('appTitle', APP_TITLE);
    window.localStorage.setItem('GROUP', GROUP);
    window.localStorage.setItem('MAP', MAP);
    window.localStorage.setItem('MAP_API_HOST', MAP_API_HOST);
    window.localStorage.setItem('MAP_TILES_HOST', MAP_TILES_HOST);
    window.localStorage.setItem('MAP_SECRET_KEY', MAP_SECRET_KEY);
    return baseApi;
  } else {
    const option = {
      method: 'GET',
      mode: 'cors'
    };
    const version = Math.random().toFixed(6);
    return fetch(`/config.json?v=${version}`, option)
      .then(response => response.json())
      .then(response => {
        const { group, appTitle, visual_api, kd3000_url, map } = response;
        if (visual_api) {
          window.localStorage.setItem('VISUAL_API', visual_api);
          window.localStorage.setItem('KD3000_URL', kd3000_url);
          window.localStorage.setItem('appTitle', appTitle ? appTitle : APP_TITLE);
          window.localStorage.setItem('GROUP', group);
          window.localStorage.setItem('MAP', map.source ? map.source : MAP);
          window.localStorage.setItem('MAP_API_HOST', map.api_host ? map.api_host : MAP_API_HOST);
          window.localStorage.setItem('MAP_TILES_HOST', map.tiles_host ? map.tiles_host : MAP_TILES_HOST);
          window.localStorage.setItem('MAP_SECRET_KEY', map.secret_key ? map.secret_key : MAP_SECRET_KEY);
          return visual_api;
        } else {
          const modal = Modal.error({
            title: '服务接口配置不正确',
            okText: "确定"
          });
          return null;
        }
      }).catch(res => {
        const modal = Modal.error({
          title: '系统异常，服务接口配置不正确',
          okText: "确定"
        });
        return null;
      });
  }
}



export default request;
